﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;

namespace DiscreteEventModel.Common {

    public class ObjectBase : IDisposable {

        private StreamBase _streamBase;

        public ObjectBase(string filePath, int dataBlockSize, int dataBlockCount) {
            this._streamBase = new StreamBase(filePath, dataBlockSize, dataBlockCount);
        }

        public ObjectBase(string filePath) {
            this._streamBase = new StreamBase(filePath);
        }

        public void Dispose() {
            this._streamBase.Dispose();
        }

        public bool TryGet<TObject>(StreamBase.Token token, out TObject obj)
            where TObject : IBinarySerializable, new() {
            StreamBase.OutputStream outputStream = this._streamBase.CreateOutputStream(token);
            if(outputStream == null) {
                obj = default(TObject);
                return false;
            }
            using(BinaryReader reader = new BinaryReader(outputStream)) {
                obj = new TObject();
                if(obj.Deserialize(reader)) {
                    return true;
                } else {
                    obj = default(TObject);
                    return false;
                }
            }
        }

        public bool TryGet<TObject>(StreamBase.Token token, Func<TObject> factory, out TObject obj)
            where TObject : IBinarySerializable {
            StreamBase.OutputStream outputStream = this._streamBase.CreateOutputStream(token);
            if(outputStream == null) {
                obj = default(TObject);
                return false;
            }
            using(BinaryReader reader = new BinaryReader(outputStream)) {
                obj = factory();
                if(obj.Deserialize(reader)) {
                    return true;
                } else {
                    obj = default(TObject);
                    return false;
                }
            }
        }

        public bool TryUpdate(StreamBase.Token token, IBinarySerializable obj) {
            StreamBase.InputStream inputStream = this._streamBase.CreateInputStream(token);
            if(inputStream == null) {
                return false;
            }
            using(BinaryWriter writer = new BinaryWriter(inputStream)) {
                obj.Serialize(writer);
            }
            return true;
        }

        public StreamBase.Token Add(IBinarySerializable obj) {
            using(BinaryWriter writer = new BinaryWriter(this._streamBase.CreateInputStream())) {
                obj.Serialize(writer);
                return (writer.BaseStream as StreamBase.InputStream).Token;
            }
        }
    }
}
